package com.jason.bookworm.service.impl;

import com.jason.bookworm.dao.pojo.*;
import com.jason.bookworm.exception.ServiceException;
import com.jason.bookworm.response.Result;
import com.jason.bookworm.response.StatusEnum;
import com.jason.bookworm.service.BookClassifyService;
import com.jason.bookworm.service.BookWareService;
import com.jason.bookworm.service.BookcaseService;
import com.jason.bookworm.service.BorrowRecordService;
import com.jason.bookworm.utils.RedisCache;
import com.jason.bookworm.utils.LoginUserUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class BookcaseServiceImpl implements BookcaseService {
    @Autowired
    private BookWareService bookWareService;

    @Autowired
    private BookClassifyService bookClassifyService;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private BorrowRecordService borrowRecordService;

    /**
     * @param num        一页的本数
     * @param classifyID 分类ID
     * @param page       第几页
     * @return 书籍列表
     */
    @Override
    public Result<List<Book>> getBooks(Integer num, Integer classifyID, Integer page) {
        BookClassify bookClassify = new BookClassify();
        bookClassify.setId(classifyID);
        List<Book> books = bookWareService.getBooksByPages(num, page, bookClassify);
        return new Result<>(StatusEnum.GET_OK, books, "获取第" + classifyID + "分类书库第" + page + "页成功！");
    }

    /**
     * @return 分类列表
     */
    @Override
    public Result<List<BookClassify>> getClassifyList() {
        List<BookClassify> classifyList = bookClassifyService.getAllBookClassify();
        if (classifyList != null) {
            return new Result<>(StatusEnum.GET_OK, classifyList, "获取分类成功！");
        } else return new Result<>(StatusEnum.GET_ERR, null, "获取分类失败！");
    }

    /**
     * @param num        一页的本数
     * @param classifyID 分类ID
     * @return 总页数
     */
    @Override
    public Result<Integer> getPages(Integer num, Integer classifyID) {
        BookClassify bookClassify = new BookClassify();
        bookClassify.setId(classifyID);
        Integer pages = bookWareService.getPageOfBooks(num, bookClassify);
        return new Result<>(StatusEnum.GET_OK, pages, "获取页数成功！");
    }

    /**
     * @param bookID 书籍id
     * @return 提交成功
     */
    @Override
    public Result<Object> reserveOneBook(String bookID) {
        Set<String> reserveSet = getReserveSetFromRedis();
        if (reserveSet.contains(bookID)) {
            return Result.getResult(StatusEnum.PUT_ERR, "提交失败！已存在相同的预约记录。");
        }
        String username = LoginUserUtil.getCurrentUsername();
        redisCache.addCacheSetValue("Reserve_" + username, bookID);
        return Result.getResult(StatusEnum.PUT_OK);
    }

    /**
     * @param bookID 书籍id
     * @return 删除成功
     */
    @Override
    public Result<Object> deleteOneBook(String bookID) {
        Set<String> reserveSet = getReserveSetFromRedis();
        if (reserveSet.isEmpty() || !reserveSet.contains(bookID)) {
            return Result.getResult(StatusEnum.DELETE_ERR);
        }
        String username = LoginUserUtil.getCurrentUsername();
        redisCache.delCacheSetValue("Reserve_" + username, bookID);
        return Result.getResult(StatusEnum.DELETE_OK);
    }

    /**
     * @return 预约书籍清单
     */
    @Override
    public Result<List<Book>> getAllReserveBook() {
        Set<String> reserveSet = getReserveSetFromRedis();
        if (reserveSet.size() == 0) {
            return new Result<>(StatusEnum.GET_ERR, "借阅列表为空");
        }
        List<Book> bookList = bookWareService.getBooksByBookIDSet(reserveSet);
        return new Result<>(StatusEnum.GET_OK, bookList);
    }

    /**
     * @return 预约成功
     */
    @Override
    public Result<Object> submitBorrowRecord(List<BorrowRecord> recordList) {
        List<Book> books = new ArrayList<>();
        //校验借阅记录合法性
        for (BorrowRecord borrowRecord : recordList) {
            //获取书籍id
            Integer bookId = borrowRecord.getBookId();
            //根据书籍id查找书籍
            Book book = bookWareService.getBookById(bookId);
            if (book == null) {
                throw new ServiceException(StatusEnum.Illegal_DATA);
            }
            //获取书籍库存
            if (book.getInventory() == 0) {
                return Result.getResult(StatusEnum.POST_ERR, "《" + book.getName() + "》这本书没有库存了！请删除这本书后再试。");
            }
            //书籍库存-1
            book.setInventory(book.getInventory() - 1);
            books.add(book);
        }
        borrowRecordService.addNewRecord(recordList);
        bookWareService.updateBatchById(books);
        //获取SecurityContextHolder的用户名
        String username = LoginUserUtil.getCurrentUsername();
        //从redis中删除该用户的借阅记录
        redisCache.deleteObject("Reserve_" + username);
        return Result.getResult(StatusEnum.POST_OK, "提交预约借阅成功！请稍后到图书馆前台领取书籍。");
    }

    //从redis中获取该用户的预约清单
    private Set<String> getReserveSetFromRedis() {
        String username = LoginUserUtil.getCurrentUsername();
        Set<String> reserveSet = redisCache.getCacheSet("Reserve_" + username);
        if (reserveSet == null) {
            reserveSet = new HashSet<>();
            redisCache.setCacheSet("Reserve_" + username, reserveSet);
            return reserveSet;
        }
        return reserveSet;
    }

    /**
     * @return 返回该用户的所有借阅记录
     */
    @Override
    public Result<List<BorrowRecord>> getAllBorrowRecord() {
        User user = LoginUserUtil.getLoginUserInfo();
        List<BorrowRecord> recordList = borrowRecordService.getAllRecords(user);
        if (recordList.isEmpty()) {
            return new Result<>(StatusEnum.GET_ERR, "借阅记录为空！");
        }
        return new Result<>(StatusEnum.GET_OK, recordList);
    }

    /**
     * @param bookIDList 根据传入的书籍id集合返回书籍列表
     * @return 书籍列表
     */
    @Override
    public Result<List<Book>> getBooks(List<String> bookIDList) {
        List<Book> bookList = bookWareService.getBooksByBookIDList(bookIDList);
        if (bookIDList.isEmpty()) {
            return new Result<>(StatusEnum.GET_ERR, "未找到任何书籍！");
        }
        return new Result<>(StatusEnum.GET_OK, bookList);
    }

    /**
     * @param bookID 获取一本书
     * @return 书籍信息
     */
    @Override
    public Result<Book> getBook(Integer bookID) {
        Book book = bookWareService.getBookById(bookID);
        if (book == null) {
            return new Result<>(StatusEnum.GET_ERR);
        }
        return new Result<>(StatusEnum.GET_OK, book);
    }

    /**
     * @return 所有书籍
     */
    @Override
    public Result<List<Book>> getAllBook() {
        List<Book> books = bookWareService.getAllBooks();
        if (books.isEmpty()) {
            return new Result<>(StatusEnum.GET_ERR);
        }
        return new Result<>(StatusEnum.GET_OK, books);
    }

    /**
     * @return 还书状态
     */
    @Override
    public Result<Object> returnOneBook(Integer bookID) {
        //获取当前用户名
        String username = LoginUserUtil.getCurrentUsername();
        //根据用户名和书籍查找借阅记录
        BorrowRecord record = borrowRecordService.getRecord(username, bookID);
        if (record == null) {
            return Result.getResult(StatusEnum.PUT_ERR, "找不到该条借阅记录！");
        }
        //还书操作
        borrowRecordService.returnBook(record);
        return Result.getResult(StatusEnum.PUT_OK, "还书成功！");
    }

    /**
     * @param recordID 根据借阅编号删除该条记录
     * @return 删除结果
     */
    @Override
    public Result<Object> deleteReturnedRecord(Integer recordID) {
        //根据id查找借阅记录
        BorrowRecord borrowRecord = borrowRecordService.getRecord(recordID);
        if (borrowRecord == null) {
            throw new ServiceException(StatusEnum.Illegal_DATA);
        }
        //获取登录用户名
        String username = LoginUserUtil.getCurrentUsername();
        //比对是否为该用户
        if (!borrowRecord.getUsername().equals(username)) {
            return Result.getResult(StatusEnum.DELETE_ERR, "你越界了！");
        }
        //判断该本书是否已还
        if (!borrowRecord.getStatus().equals("1")) {
            return Result.getResult(StatusEnum.DELETE_ERR, "想白嫖？门都没有。");
        }
        borrowRecordService.deleteRecord(borrowRecord);
        return Result.getResult(StatusEnum.DELETE_OK);
    }
}
